package dev.mcdd.config;


import dev.mcdd.security.handler.AuthenticationExceptionHandler;
import dev.mcdd.security.handler.LoginAuthenticationHandler;
import dev.mcdd.security.handler.LogoutAuthenticationHandler;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;

/**
 * WebSecurityConfiguration
 *
 * @author: mcdd1024
 * @date 2025/1/16 05:23
 */
@Slf4j
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@RequiredArgsConstructor
public class WebSecurityConfiguration {

    private final LoginAuthenticationHandler loginAuthenticationHandler;
    private final LogoutAuthenticationHandler logoutAuthenticationHandler;
    private final AuthenticationExceptionHandler authenticationExceptionHandler;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

        http.csrf(AbstractHttpConfigurer::disable);

        http.sessionManagement(conf -> conf
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS));

        http.authorizeHttpRequests(requests -> requests
            .requestMatchers("/api/v1/users/**").permitAll()
            .requestMatchers("/api/v1/auth/**", "/error").permitAll()
            .requestMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll()
            .anyRequest().authenticated());

        http.formLogin(login -> login
            .loginProcessingUrl("/api/v1/auth/login")
            .usernameParameter("text")
            .successHandler(loginAuthenticationHandler)
            .failureHandler(loginAuthenticationHandler)
            .permitAll());

        http.logout(logout -> logout
            .logoutUrl("/api/v1/auth/logout")
            .logoutSuccessHandler(logoutAuthenticationHandler));

        http.exceptionHandling(handling -> handling
            .accessDeniedHandler(authenticationExceptionHandler)
            .authenticationEntryPoint(authenticationExceptionHandler));

        return http.build();
    }

}
